package max.ta.stock.plot.data;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import max.ta.data.entity.StockQuote;
import max.ta.data.plot.data.MathLine;
import max.ta.data.plot.data.MathPoint;

public class StockPointSetBuilder {

    protected final StockSurface series = new StockSurface();
    private boolean enableOpen = true;
    private boolean enableLow = true;
    private boolean enableHigh = true;
    private boolean enableClose = true;
    private boolean enableVolume = true;

    public StockPointSetBuilder() {
	super();
    }

    public boolean isEnableOpen() {
	return enableOpen;
    }

    public void setEnableOpen(boolean enableOpen) {
	this.enableOpen = enableOpen;
    }

    public boolean isEnableLow() {
	return enableLow;
    }

    public void setEnableLow(boolean enableLow) {
	this.enableLow = enableLow;
    }

    public boolean isEnableHigh() {
	return enableHigh;
    }

    public void setEnableHigh(boolean enableHigh) {
	this.enableHigh = enableHigh;
    }

    public boolean isEnableClose() {
	return enableClose;
    }

    public void setEnableClose(boolean enableClose) {
	this.enableClose = enableClose;
    }

    public boolean isEnableVolume() {
	return enableVolume;
    }

    public void setEnableVolume(boolean enableVolume) {
	this.enableVolume = enableVolume;
    }

    public StockSurface getStockData() {
	return series;
    }

    public void buildSeries(List<StockQuote> quotes) {
	series.clear();
	// --- OPEN -----------------------------------------------------------------------------
	if (enableOpen) {
	    MathLine<Date, Double> openPointsSet = new MathPointSetBuilder("Open") {

		@Override
		public Double getValue(StockQuote q) {
		    return q.getOpen();
		}
	    }.build(quotes);
	    series.setOpen(openPointsSet);
	}
	// --- LOW -----------------------------------------------------------------------------
	if (enableLow) {
	    MathLine<Date, Double> lowPointsSet = new MathPointSetBuilder("Low") {

		@Override
		public Double getValue(StockQuote q) {
		    return q.getLow();
		}
	    }.build(quotes);
	    series.setLow(lowPointsSet);
	}
	// --- HIGH -----------------------------------------------------------------------------
	if (enableHigh) {
	    MathLine<Date, Double> highPointsSet = new MathPointSetBuilder("High") {

		@Override
		public Double getValue(StockQuote q) {
		    return q.getHigh();
		}
	    }.build(quotes);
	    series.setHigh(highPointsSet);
	}
	// --- CLOSE -----------------------------------------------------------------------------
	if (enableClose) {
	    MathLine<Date, Double> closePointsSet = new MathPointSetBuilder("Close") {

		@Override
		public Double getValue(StockQuote q) {
		    return q.getClose();
		}
	    }.build(quotes);
	    series.setClose(closePointsSet);
	}// --- VOLUME -----------------------------------------------------------------------------
	if (enableVolume) {
	    MathLine<Date, Double> vlumePointsSet = new MathPointSetBuilder("Volume") {

		@Override
		public Double getValue(StockQuote q) {
		    return q.getVolume();
		}
	    }.build(quotes);
	    series.setVolume(vlumePointsSet);
	}
    }

    private abstract class MathPointSetBuilder {

	private final String serieName;

	public MathPointSetBuilder(String serieName) {
	    super();
	    this.serieName = serieName;
	}

	public MathLine<Date, Double> build(List<StockQuote> quotes) {
	    MathLine<Date, Double> pointSet = new MathLine<Date, Double>(serieName);
	    List<MathPoint<Date, Double>> points = new ArrayList<MathPoint<Date, Double>>();
	    for (StockQuote q : quotes) {
		MathPoint<Date, Double> point = new MathPoint<Date, Double>(q.getDate(), getValue(q));
		points.add(point);
	    }
	    pointSet.addAll(points);
	    return pointSet;
	}

	public abstract Double getValue(StockQuote q);
    }

    @Override
    public String toString() {
	return "StockPointSetBuilder [O=" + enableOpen + "-L=" + enableLow + "-H=" + enableHigh + "-C=" + enableClose + "-V=" + enableVolume + ", series="
		+ series.getSize() + "]";
    }
}
